home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Collection of Tools & Utilities
/
Collection of Tools and Utilities.iso
/
basic
/
bardcol2.zip
/
BARDCOL1.EXE
/
RSCROLL.ASM
< prev
Wrap
Assembly Source File
|
1987-04-18
|
8KB
|
165 lines
;********** RScroll.Asm - horizontal scrolling routine: RIGHT
;Copyright (c) 1987 by Ethan Winer
;Syntax - Call RScroll(UL.Row%, UL.Col%, LR.Row%, LR.Col%, Columns%)
; 1-25 1-80 1-25 1-80 1-79
Code Segment Byte
Assume CS:Code
RScroll Proc Far
Begin: Push BP ;save BP and DS for Turbo Basic
Push DS
Mov BP,SP
;Get passed parameters and calculate the number of rows, columns, and window width
Mov SI,[BP+24] ;put address of UL.Row% into SI
Mov DS,[BP+26] ;put segment of UL.Row into DS
Mov AL,[SI] ;put UL.Row% into AL
Dec AL ;adjust 1-25 to 0-24 for calculations below
Mov CL,160 ;prepare to multiply AL by 160
Mul CL ;now AX holds beginning address of upper row in screen memory
Mov SI,[BP+12] ;put address of LR.Col% into SI
Mov DS,[BP+14] ;ditto for segment
Mov BX,[SI] ;put LR.Col% into BX
Dec BX ;adjust for addition below
Add AX,BX ;add column offset to AX to determine actual start address of screen portion to be scrolled
Add AX,BX ;once more to include the attribute bytes
Mov BX,AX ;now BX, which will hold the destination address, is the same as the source address
Mov SI,[BP+08] ;put address of Columns% into SI
Mov DS,[BP+10]
Add BX,[SI] ;add to BX to get destination address of memory moves
Add BX,[SI] ;once more to include the attribute bytes
;Determine the type of monitor by looking at the equipment list at 0000:0410h
Mov CX,0 ;set ES to 0 through CX to look at the equipment list in low memory
Mov ES,CX
Mov CX,0B000h ;set CX to hold mono screen segment initially, we'll add 800h later if color
Mov DL,ES:[410h] ;get equipment list byte - bit coded to indicate monitor type etc.
And DL,30h ;keep only the bits we care about
Cmp DL,30h ;is it mono?
JZ Mono_EGA ;yes, skip over adding 800h to CX (which will end up in the segment registers DS and ES)
Add CX,800h ;adjust CX to segment of color screen
Mov DL,ES:[487h] ;if an EGA is installed, this byte will not be zero
Cmp DL,0 ;is it an EGA?
JNZ Mono_EGA ;yes, skip over
Mov DX,3DAh ;no, specify the port to check for retrace
Jmp Continue ;and skip over
Mono_EGA: Mov DX,0 ;indicate that we don't need to wait for a retrace later
;Continue getting the passed parameters
Continue: Mov ES,CX ;now ES holds the correct segment for the type of screen in use
Mov SI,[BP+16] ;put address of LR.Row% into SI
Mov DS,[BP+18]
Mov CH,[SI] ;put LR.Row% into CH
Mov SI,[BP+24] ;get address for UL.Row%
Mov DS,[BP+26]
Sub CH,[SI] ;subtract it from CH to get the number of rows to be processed
Inc CH ;add 1 because Number_Of_Rows = (LR.Row% - UL.Row%) + 1
Mov SI,[BP+12] ;put address of LR.Col% into SI
Mov DS,[BP+14]
Mov CL,[SI] ;put LR.Col% into CL
Mov SI,[BP+20] ;get address for UL.Col%
Mov DS,[BP+22]
Sub CL,[SI] ;subtract it from CL to get the number of columns to scroll for each row processed
Inc CL ;add 1 because Number_Of_Columns = (LR.Col% - UL.Col%) + 1
;Scroll the screen
Push ES ;make both the source and destination segments the same through the stack
Pop DS ;since the instruction MOV DS,ES is not allowed
Std ;setar direction flag so all memory moves below will be in the backward direction
Next_Row: Mov SI,AX ;put the starting source address for moves into SI
Mov DI,BX ;ditto for the starting destination address
Push AX ;save AX because it will get clobbered below
Next_Col: Cmp DL,0 ;are we doing a mono or EGA screen?
JZ Mono ;yes, skip over waiting for the CGA retrace signal
NRetrace: In AL,DX ;wait until not doing a retrace
Test AL,1
JNZ NRetrace
Retrace: In AL,DX ;get the video status byte
Test AL,1 ;check just the retrace bit - are we doing a retrace now?
JZ Retrace ;no, wait until we are
Mono: Lodsw ;get the source character and atrribute
Stosw ;and put it in its new home
Dec CL ;show that we just did a column
Jnz Next_Col ;continue until CL is zero (done with this row)
;Calculate the number of trailing columns to blank out
Pop AX ;retrieve starting address from before
Push AX ;save again for later
Push BX ;save BX for a moment
Sub BX,AX ;the difference between the original source and destination addresses tells how many columns
Shr BL,1 ;actually, the difference is twice the number of columns, so divide by two
Mov CL,BL ;and put the count from BL into CL
Pop BX ;retrieve original destination address
;Re-calculate the window width - can't get at the original variables anymore because DS now holds the screen segment
Pop AX ;retrieve starting address again
Push AX ;save again
Sub AX,SI ;the difference between SI and AX (where SI was before) tells how many columns were moved
Shr AL,1 ;again, the difference is twice the width because of the attribute bytes, divide by two
Mov AH,AL ;save it in AH because AL gets changed below
;Fill remaining columns with blanks
Next_Spc: Cmp DL,0 ;are we doing mono or EGA?
JZ Mono2 ;yes, skip over waiting for retrace
NRetrace2: In AL,DX ;wait until not doing a retrace
Test AL,1
JNZ NRetrace2
Retrace2: In AL,DX ;get video status byte
Test AL,1 ;are we doing a retrace now?
JZ Retrace2 ;no, wait until we are
Mono2: Mov AL,32 ;put a blank space into AL to clear rightmost columns after scrolling
Stosb ;put it onto the screen
Dec DI ;skip over the attribute byte to leave the current color undisturbed
Dec CL ;decrement the counter that tracks how many blanks we've done so far
Jnz Next_Spc ;until done
Mov CL,AH ;retrieve the number of columns to scroll calculated earlier
;Calculate the addresses for the next row
Pop AX ;retrieve AX
Add AX,160 ;point source address to the next row down
Add BX,160 ;ditto for the destination
Dec CH ;show that we just completed another row
Jnz Next_Row ;do the next row if there still is one to do
Done: Pop DS
Pop BP
RScroll Endp
Code Ends
End Begin